﻿using System;
using System.Threading.Tasks;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Microsoft.VisualStudio.TestPlatform.UnitTestFramework;
using MugenMvvmToolkit.Interfaces;
using MugenMvvmToolkit.Interfaces.ViewModels;
using MugenMvvmToolkit.Utils;
using MugenMvvmToolkit.ViewModels;
using Should;

namespace MugenMvvmToolkitTest.ViewModel
{
    [TestClass]
    public class WorkspaceViewModelTest : CloseableViewModelTest
    {
        #region Nested types

        public class TestWorkspaceViewModel : WorkspaceViewModel
        {
        }

        public class EventWorkspaceViewModel : WorkspaceViewModel
        {
            #region Properties

            public bool CanCloseValue { get; set; }

#if TASKSUPPORT
            public Func<object, Task<bool>> OnClosingCallback { get; set; }
#else
            public Func<object, IOperationResult<bool>> OnClosingCallback { get; set; }
#endif
            public bool OnClosedInvoke { get; set; }

            #endregion

            #region Overrides of WorkspaceViewModel

            /// <summary>
            ///     Determines whether the specified command <c>CloseCommand</c> can be execute.
            /// </summary>
            /// <param name="param">The specified command parameter.</param>
            /// <returns>
            ///     If <c>true</c> - can execute, otherwise <c>false</c>.
            /// </returns>
            protected override bool CanClose(object param)
            {
                return CanCloseValue;
            }

#if TASKSUPPORT
            /// <summary>
            ///     Occurs when view model closing.
            /// </summary>
            /// <returns>
            ///     If <c>true</c> - close, otherwise <c>false</c>.
            /// </returns>
            protected override Task<bool> OnClosing(object parameter)
            {
                if (OnClosingCallback == null)
                    return MvvmUtils.TrueTaskResult;
                return OnClosingCallback(parameter);
            }
#else
            /// <summary>
            ///     Occurs on closing current view model.
            /// </summary>
            /// <returns>
            ///     If <c>true</c> - close, otherwise <c>false</c>.
            /// </returns>
            protected override IOperationResult<bool> OnClosing(object parameter)
            {
                if (OnClosingCallback == null)
                    return MvvmUtils.TrueOperationResult;
                return OnClosingCallback(parameter);
            }
#endif
            /// <summary>
            ///     Occurs when <c>CloseCommand</c> executed.
            /// </summary>
            protected override void OnClosed(object parameter)
            {
                OnClosedInvoke = true;
                base.OnClosed(parameter);
            }

            #endregion
        }

        #endregion

        #region Test methods

        [TestMethod]
        public void CanExecuteShouldReturnResultFromCanClose()
        {
            var viewModel = GetViewModel<EventWorkspaceViewModel>();
            viewModel.CanCloseValue = false;
            viewModel.CloseCommand.CanExecute(null).ShouldBeFalse();

            viewModel.CanCloseValue = true;
            viewModel.CloseCommand.CanExecute(null).ShouldBeTrue();
        }

        [TestMethod]
        public void OnClosedShouldBeCalledWhenVmClosed()
        {
            var viewModel = GetViewModel<EventWorkspaceViewModel>();
            viewModel.OnClosedInvoke.ShouldBeFalse();
            viewModel.Close(null);
            viewModel.OnClosedInvoke.ShouldBeTrue();
        }

#if TASKSUPPORT
        [TestMethod]
        public void OnClosingShouldBeCalledWhenVmClosing()
        {
            var viewModel = GetViewModel<EventWorkspaceViewModel>();
            viewModel.OnClosingCallback = o => MvvmUtils.FalseTaskResult;
            viewModel.Close(null).Result.ShouldBeFalse();

            viewModel.OnClosingCallback = o => MvvmUtils.TrueTaskResult;
            viewModel.Close(null).Result.ShouldBeTrue();
        }
#else
        [TestMethod]
        public void OnClosingShouldBeCalledWhenVmClosing()
        {
            var viewModel = GetViewModel<EventWorkspaceViewModel>();
            viewModel.OnClosingCallback = o => MvvmUtils.FalseOperationResult;
            viewModel.Close(null).Result.ShouldBeFalse();

            viewModel.OnClosingCallback = o => MvvmUtils.TrueOperationResult;
            viewModel.Close(null).Result.ShouldBeTrue();
        }
#endif
        #endregion

        #region Overrides of CloseableViewModelTest

        protected override INotifyViewModelClosing GetCloseableViewModelInternal()
        {
            return new TestWorkspaceViewModel();
        }

        #endregion
    }
}